package Railroad.GUI;

import Railroad.Components.Switch;
import Railroad.Components.SwitchStatus;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;

public class SwitchDraw {
    private final Switch sw;
    private final Graphics2D graphics;
    private final boolean background;
    private final int midXSide, midXStraight;
    private final int rasterX;
    private final int rasterY;
    private final Color activeColor, defaultColor, unknownColor, blackColor;
    private final boolean right, up;
    private final int strokeWidth;
    
    /*
                    | midXSide
                    v
                ----
                    \
                     \
                      \
                --------------
                       ^
                       | midXStraight
        */

    public SwitchDraw(Switch sw, Graphics2D graphics, boolean background) {
        this.sw = sw;
        this.graphics = graphics;
        this.background = background;
        
        rasterX = RailroadPanel.rasterX;
        rasterY = RailroadPanel.rasterY;
        
        activeColor = sw.getColor();
        defaultColor = Switch.defaultColor;//v track item asi ymenit nech to neni t
        unknownColor = defaultColor;
        blackColor = new Color(0,0,0);
        
        right = sw.getStartX() < sw.getEndX();
        if (right) {
            midXSide = sw.getEndX() - sw.getSraightEnd();
            midXStraight = sw.getStartX() + sw.getSraightStart();
        }
        else {
            midXSide = sw.getEndX() + sw.getSraightEnd();
            midXStraight = sw.getStartX() - sw.getSraightStart();
        }
        
        up = sw.getDirectY() > sw.getSideY();
        
        strokeWidth = 2;
    }
    
    
    public void draw() {
        graphics.setStroke(new BasicStroke(strokeWidth));
        if (background && sw.getStatus() == SwitchStatus.UNKNOWN)
        drawIntersection();//privadzacia
      //  drawBG();
        drawCommonStraightPart(); //privadzacia
        drawDirectStraightPart(); //rovna
        drawSidePart();//sikma cast        
    }
    
    private void drawBG()
    {
        graphics.drawRect(midXStraight, sw.getDirectY(),5, 5);
    }
    private void drawIntersection() {//spitat sa na co to je
        graphics.setColor(unknownColor);
        int pointX = midXStraight * rasterX;
        int pointY = sw.getDirectY() * rasterY;
        graphics.fillRect(pointX, pointY, rasterX, rasterY);
    }
    
    
    private void drawCommonStraightPart() {
        graphics.setColor(activeColor);
        drawLine(sw.getStartX(), sw.getDirectY(), (midXStraight - sw.getStartX()), 0);
    }
    
    
    private void drawDirectStraightPart() {
        if (background)
            graphics.setColor(blackColor);
        else if (sw.getStatus() == SwitchStatus.STRAIGHT)
            graphics.setColor(activeColor);
        else
            graphics.setColor(defaultColor);
        int width = sw.getEndX() - midXStraight;
        if (background || sw.getStatus() == SwitchStatus.STRAIGHT)
            width += (right ? 1 : -1);
        drawLine(sw.getEndX(), sw.getDirectY(), -width, 0); // rovna priama cast vyhybky (bez toho spolocneho)
    }

    
    private void drawSidePart() {
        if (sw.getStatus() == SwitchStatus.SIDE)
            graphics.setColor(activeColor);
        else
            graphics.setColor(defaultColor);
        drawSideStraight();       
        drawSideSkew(); 
    }

    private void drawSideStraight() {
        drawLine(sw.getEndX(), sw.getSideY(), sw.getSraightEnd() * (right ? -1 : 1), 0);
    }

    private void drawSideSkew() {
        if (background)
            graphics.setColor(blackColor);
        
        int skipX = 0;
        int skipY = 0;
        if (sw.getStatus() == SwitchStatus.STRAIGHT ||
                sw.getStatus() == SwitchStatus.UNKNOWN && !background) {
            skipY = rasterY / 2;
            if (!up) skipY = -skipY;
            float ratio = ((float)Math.abs(midXSide - midXStraight) + 1) / (Math.abs(sw.getDirectY() - sw.getSideY()));
            skipX = -(int)(skipY * ratio * rasterX / rasterY);
            if (!up && right || up && !right) skipX = -skipX;
        }
        
        int x1 = midXSide * rasterX;
        int y1 = sw.getSideY() * rasterY;
        int x2 = midXStraight * rasterX - skipX;
        int y2 = sw.getDirectY() * rasterY - skipY;
        if (right)
            x1 += rasterX;
        else
            x2 += rasterX;
        y1 += rasterY / 2;
        y2 += rasterY / 2;
        graphics.drawLine(x1, y1, x2, y2);
    }
    
    
    
    private void drawLine(int x, int y, int width, int height) {
        drawLine(x, y, width, height, true, true);
    }
            
    private void drawLine(int x, int y, int width, int height, boolean extendX, boolean extendY) {        
        int nx1 = x * rasterX + rasterX / 2;
        int nx2 = (x + width) * rasterX + rasterX / 2;
        
        if (extendX) {
            if (nx1 < nx2) {
                nx1 -= rasterX / 2 - strokeWidth / 2;
                nx2 -= rasterX / 2 + (strokeWidth + 1) / 2;
            }
            else if (nx1 > nx2) {
                nx1 += rasterX / 2 - (strokeWidth + 1) / 2;
                nx2 += rasterX / 2 + strokeWidth / 2;
            }
        }

        int ny1 = y * rasterY + rasterY / 2;
        int ny2 = (y + height) * rasterY + rasterY / 2;
        
        if (extendY) {
            if (ny1 < ny2) {
                ny1 -= rasterY / 2 - strokeWidth / 2;
                ny2 -= rasterY / 2 + (strokeWidth + 1) / 2;
            }
            else if (ny1 > ny2) {
                ny1 += rasterY / 2 - (strokeWidth - 1) / 2;
                ny2 += rasterY / 2 + (strokeWidth + 2) / 2;
            }
        }
        
        graphics.drawLine(nx1, ny1, nx2, ny2);
    }
}
